package wpRelations;

import java.util.ArrayList;
import java.util.HashMap;

import processing.core.PApplet;
import processing.core.PVector;
import wpRelations.WP_002.Edge;
import wpRelations.WP_002.Node;

public class WP_005_rangTest extends PApplet {

	/**
	 * @param args
	 */
	
	TsvTable rawData;
	ArrayList<String> rangListZero;
	ArrayList<String> rangListOne;
	ArrayList<String> rangListTwo;
	String articleName = "Coby_Miller";
	String fileName = "Coby_Miller_stuff.tsv";
	
	//Node[] nodes = new Node[100];
	ArrayList<Node> nodes = new ArrayList();
	HashMap nodeTable = new HashMap();
	public int nodeCount;
	public int[] nCount = new int[3];
	//public int[] nodeCount;
	
	int edgeCount;
	//	Edge[] edges = new Edge[500];
	ArrayList<Edge> edges = new ArrayList();
	static final int nodeColor   = 0xF0C070;
	static final int selectColor = 0xFF3030;
	static final int fixedColor  = 0xFF8080;
	static final int edgeColor   = 0x000000;
	
	float nodeMassMax;
	
	
	public void setup() {
		size(1000,1000,OPENGL);
		smooth();
		rangListZero = new ArrayList<String>();
		rangListOne = new ArrayList<String>();
		rangListTwo = new ArrayList<String>();
		rangListZero.add(articleName);
		rawData = new TsvTable(this, fileName);
		System.out.println("The table " + fileName + " has " + rawData.getRowCount() + " rows.");
		System.out.println("The table " + fileName + " has " + rawData.data[0].length + " coloumns.");
		for (int i = 0; i < rawData.getRowCount(); i++) {
			if (!rawData.getString(i, 2).equalsIgnoreCase("category")) {
				String fromLink =rawData.getString(i, 0);	
				String toLink =rawData.getString(i, 1);
				if (fromLink.equalsIgnoreCase(articleName)) {
					if (!rangListOne.contains(toLink)) {
						rangListOne.add(toLink);
					}
				} else {
					if (toLink.equalsIgnoreCase(articleName)) {
						if (!rangListOne.contains(fromLink)) {
							rangListOne.add(fromLink);
						}
					}
				}
			}			 
		}
		for (int i = 0; i < rawData.getRowCount(); i++) {
			if (!rawData.getString(i, 2).equalsIgnoreCase("category")) {
				String fromLink =rawData.getString(i, 0);	
				String toLink =rawData.getString(i, 1);
				if (!rangListTwo.contains(fromLink) && !rangListOne.contains(fromLink) && !rangListZero.contains(fromLink)) {
					rangListTwo.add(fromLink);
				}
				if (!rangListTwo.contains(toLink) && !rangListOne.contains(toLink) && !rangListZero.contains(toLink)) {
					rangListTwo.add(toLink);
				}
//				if (!rangListTwo.contains(toLink) && !rangListZero.contains(toLink) && !rangListOne.contains(toLink) && !rangListZero.contains(toLink) ) {
//					rangListTwo.add(toLink);
//				}
			}
		}
		System.out.println("RangLinst 0 has " + rangListZero.size() + " elements.");
//		System.out.println(rangListZero.toString());
//		System.out.println();
		System.out.println("RangLinst 1 has " + rangListOne.size() + " elements.");
//		System.out.println(rangListOne.toString());
//		System.out.println();
		System.out.println("RangLinst 2 has " + rangListTwo.size() + " elements.");
		//creating edges nodes
			for (int i = 0; i < rawData.getRowCount(); i++) {
				if (!rawData.getString(i, 2).equalsIgnoreCase("category")) {
					String from = rawData.getString(i, 0); 
					String to = rawData.getString(i, 1);
					int fromRang = -1;
					int toRang = -1;
					if(rangListZero.contains(from)) fromRang = 0;
					if(rangListOne.contains(from)) fromRang = 1;
					if(rangListTwo.contains(from)) fromRang = 2;
					if(rangListZero.contains(to)) toRang = 0;
					if(rangListOne.contains(to)) toRang = 1;
					if(rangListTwo.contains(to)) toRang = 2;
					float addMass = 0f;
					if (fromRang != -1 && toRang != -1) {
						//TODO: some more mass adding algorithm, eg. toRang == 2;
						addMass = 1f;
					}
					addEdge(from, to, fromRang, toRang, addMass);
				}
			}
		
		//distributing edge mass to nodes
			nodeMassMax = 0;
			System.out.println("edge count: "+edges.size());
			System.out.println("node count: "+nodes.size());
			for (int i = 0; i < edges.size(); i++) {
				edges.get(i).from.adMass(edges.get(i).mass);
				edges.get(i).to.adMass(edges.get(i).mass);
				if (nodeMassMax < edges.get(i).from.massAbs) nodeMassMax =edges.get(i).from.massAbs; 
				if (nodeMassMax < edges.get(i).to.massAbs) nodeMassMax =edges.get(i).to.massAbs;
				
			}
			System.out.println("maximal node mass: " + nodeMassMax);
	    //normalizing node mass
			for (int i = 0; i < nodes.size(); i++) nodes.get(i).normMass(nodeMassMax);
			//counting / sorting (?) nodes
			for (int i = 0; i < nodes.size(); i++) {
				if (nodes.get(i).rang > -1) nCount[nodes.get(i).rang]++;
				}
			System.out.println("There are " + nCount[0] + " nodes of rang 0.");
			System.out.println("There are " + nCount[1] + " nodes of rang 1.");
			System.out.println("There are " + nCount[2] + " nodes of rang 2.");
		// setting up positions
			float[] xInc = new float[3];
			xInc[0] = width/2f;
			xInc[1] = width/(float)nCount[1];
			xInc[2] = width/(float)nCount[2];
			int[] iter = new int[3];
			for (int i = 0; i < nodes.size(); i++) {
				int r = nodes.get(i).rang;
				float m = nodes.get(i).massNorm;
				//PVector v = new PVector(xInc[r]*iter[r],height-height*m,0);
				PVector v = new PVector(500,500,0);
				nodes.get(i).setPos(v);
				iter[r]++;
			}
		}
	
		public void draw() {
			background(255,255,0);
			displayBensGraph(0.95f);
			System.out.println("finshed drawing.");
			
		}
	
	void addEdge(String fromLabel, String toLabel, int fromRang, int toRang, float addMass) {
		  // Filter out unnecessary words
		 // if (ignoreWord(fromLabel) || ignoreWord(toLabel)) return;

		  Node from = findNode(fromLabel, fromRang);
		  Node to = findNode(toLabel, toRang);
//		  from.increment();
//		  to.increment();
		  
		  for (int i = 0; i < edges.size(); i++) {
		    if (edges.get(i).from == from && edges.get(i).to == to) {
		      edges.get(i).addMass(addMass);
		      return;
		    }
		  } 
		  
		  Edge e = new Edge(from, to);
		  e.addMass(addMass);
//		  if (edgeCount == edges.length) {
//		    edges = (Edge[]) expand(edges);
//		  }
//		  edges[edgeCount++] = e;
		  edges.add(e);
		}



//		String[] ignore = { "a", "of", "the", "i", "it", "you", "and", "to" };
	//
//		boolean ignoreWord(String what) {
//		  for (int i = 0; i < ignore.length; i++) {
//		    if (what.equals(ignore[i])) {
//		      return true;
//		    }
//		  }
//		  return false;
//		}


		Node findNode(String label, int rang) {
		  label = label.toLowerCase();
		  Node n = (Node) nodeTable.get(label);
		  if (n == null) {
		    return addNode(label, rang);
		  }
		  return n;
		}


		Node addNode(String label, int rang) {
		  Node n = new Node(label, rang);  
//		  if (nodeCount == nodes.length) {
//		    nodes = (Node[]) expand(nodes);
//		  }
		  nodeTable.put(label, n);
//		  nodes[nodeCount++] = n;
		  nodes.add(n);
		  return n;
		}





		boolean record;
		
		void displayBensGraph () {
			  for (int i = 0 ; i < 100; i++) {
			    edges.get(i).draw();
			  }
			  for (int i = 0 ; i < 100; i++) {
			    nodes.get(i).draw();
			  }
		}
		void displayBensGraph (float threshold) {
			for (int i = 0 ; i < edges.size(); i++) {
				edges.get(i).draw();
			}
			for (int i = 0 ; i < nodes.size(); i++) {
				if(nodes.get(i).massNorm >= threshold) nodes.get(i).draw();
			}
		}
		
		public void keyPressed() {
		  if (key == 'r') {
		    record = true;
		  }
		}


		Node selection; 


		public void mousePressed() {
		  // Ignore anything greater than this distance
		  float closest = 20;
		  for (int i = 0; i < nodeCount; i++) {
		    Node n = nodes.get(i);
		    float d = dist(mouseX, mouseY, n.pos.x, n.pos.y);
		    if (d < closest) {
		      selection = n;
		      closest = d;
		    }
		  }
		  if (selection != null) {
		    if (mouseButton == LEFT) {
		      selection.fixed = true;
		    } else if (mouseButton == RIGHT) {
		      selection.fixed = false;
		    }
		  }
		}


		public void mouseDragged() {
		  if (selection != null) {
		    selection.pos.x = mouseX;
		    selection.pos.y = mouseY;
		  }
		}


		public void mouseReleased() {
		  selection = null;
		}
		// Code from Visualizing Data, First Edition, Copyright 2008 Ben Fry.
		// Based on the GraphLayout example by Sun Microsystems.


		public class Edge {
		  Node from;
		  Node to;
		  float len;
		  float mass;

		  Edge(Node from, Node to) {
		    this.from = from;
		    this.to = to;
		    //this.len = 250;
		    mass = 0f;
		  }
		  
		  
		  void addMass(float theMass) {
		    mass+=theMass;
		  }

		  void draw() {
		   // stroke(edgeColor);
			stroke(255,127);
		    strokeWeight(0.35f);
		    strokeWeight(3.5f);
		    beginShape();
		    vertex(from.pos.x,from.pos.y,from.pos.z);
		    vertex(to.pos.x,to.pos.y,to.pos.z);
		    endShape();
		    
		  }
		}
		  
		
		// Code from Visualizing Data, First Edition, Copyright 2008 Ben Fry.
		// Based on the GraphLayout example by Sun Microsystems.


		public class Node {
		  PVector pos;
		  boolean fixed;
		  String label;
		  //int count;
		  int rang;
		  float massAbs, massNorm;

		  Node(String label, int theRang) {
			rang = theRang;
		    this.label = label;
		    massAbs =0;
		    massNorm =0;
		  }
		  
		  void setPos(PVector thePos) {
			  pos = thePos;
		  }
		  
		  void adMass(float theMass) {
			  massAbs += theMass;
		  }

		  void normMass (float maxMass) {
			  massNorm /= maxMass;
		  }

		  void draw() {
		    //stroke(0);
		    //strokeWeight(0.5f);
		    fill(255,0,127);
		    stroke(255);
		    strokeWeight(10);
		    ellipse(pos.x, pos.y, 10*massNorm, 10*massNorm);
		    point(pos.x, pos.y, pos.z);
		    float w = textWidth(label);
		    textAlign(CENTER, CENTER);
		      fill(0,63);
		      //text(label, pos.x, pos.y);
		  }
		}

	
	
//	public static void main(String[] args) {
//		// TODO Auto-generated method stub
//
//	}

}
